﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using ProgNetComponents.Interfaces;
using ProgNetComponents.Collections;
using ProgNetComponentsDx.Design.Editors;
using ProgNetComponents.Design.Editors;

namespace ProgNetComponentsDx.Design.Designers
{
    public partial class BaseGroupCollectionDesigner : Form
    {
        public static BaseGroupCollectionDesigner Instance;
        private static BaseGroupCollectionDesigner PrevInstance;


        public BaseGroupCollectionDesigner()
        {
            InitializeComponent();
        }
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            propertyGrid1.SelectedObject = e.Node.Tag;
        }

        private IList _Collection = null;
        public IList Collection
        {
            get { return _Collection; }
            set
            {
                _Collection = value;

                if (_Collection != null)
                {
                    foreach (INamedGroup g in _Collection)
                    {
                        AddGroupNode(null, g);
                    }
                }
            }
        }

        private TreeNode CreateGroupNode(INamedGroup g)
        {
            TreeNode n = new TreeNode();
            n.BackColor = BaseGroupItemNameEditor.GroupColor;
            n.Tag = g;
            n.Text = "[Group] " + g.Name;
            return n;
        }

        private TreeNode CreateItemNode(INamedObject o)
        {
            TreeNode n = new TreeNode();
            n.BackColor = ProgNetComponents.Design.Editors.BaseGroupItemNameEditor.ItemColor;
            n.Tag = o;
            n.Text = o.Name;
            return n;
        }

        private void AddOptionsNodes(TreeNode parent, INamedGroup g)
        {
            if (parent != null)
            {
                foreach (INamedObject o in g.Items)
                {
                    parent.Nodes.Add(CreateItemNode(o));
                }
            }
        }

        private void AddGroupNode(TreeNode parent, INamedGroup g)
        {
            TreeNode n = CreateGroupNode(g);

            if (parent != null)
                parent.Nodes.Add(n);
            else
                treeView1.Nodes.Add(n);

            AddOptionsNodes(n, g);

            foreach (INamedGroup g2 in g.Groups)
            {
                AddGroupNode(n, g2);
            }
        }

        private void FillCollection(IList Collection)
        {
            Collection.Clear();
            foreach (TreeNode n in treeView1.Nodes)
            {
                if (n.Tag is INamedGroup)
                    AddGroup(n, null);
            }
        }

        private void AddGroup(TreeNode n, INamedGroup parent)
        {
            if (parent != null)
                parent.Groups.Add(n.Tag as INamedGroup);
            else
                Collection.Add(n.Tag as INamedGroup);
            foreach (TreeNode n2 in n.Nodes)
            {
                if (n2.Tag is INamedGroup)
                    AddGroup(n2, n.Tag as INamedGroup);
                else if (parent != null)
                {
                    (n.Tag as INamedGroup).Items.Add(n2.Tag as INamedObject);
                }
            }
        }

        private void btnDel_Click(object sender, EventArgs e)
        {
            TreeNodeCollection nodes = null;

            TreeNode n = treeView1.SelectedNode;

            TreeNode n2 = null;
            if (n != null)
            {
                if (n.Parent != null)
                    nodes = n.Parent.Nodes;
                else
                    nodes = treeView1.Nodes;

                n2 = n.NextNode;
                if (n2 == null)
                    n2 = n.PrevNode;

                if (n.Parent != null)
                {
                    if (n2 == null)
                        n2 = n.Parent;
                    if (n.Parent.Tag is INamedGroup)
                    {
                        INamedGroup group = n.Parent.Tag as INamedGroup;
                        if (n.Tag is INamedGroup)
                            group.Groups.Remove(n.Tag as INamedGroup);
                        else
                            group.Items.Remove(n.Tag as INamedObject);
                    }
                }
                nodes.Remove(n);
            }
            treeView1.SelectedNode = n2;
            treeView1.Focus();
        }

        private void btnAddRoot_Click(object sender, EventArgs e)
        {
            AddGroupTreeNode(false);
        }

        private void btnAddChild_Click(object sender, EventArgs e)
        {
            AddGroupTreeNode(true);
        }

        private void AddGroupTreeNode(bool child)
        {
            TreeNode selectedGroupNode = treeView1.SelectedNode;
            TreeNodeCollection nodes = null;
            if (selectedGroupNode != null)
            {
                if (!(selectedGroupNode.Tag is INamedGroup))
                {
                    selectedGroupNode = selectedGroupNode.Parent;
                }
                if (!child)
                    selectedGroupNode = selectedGroupNode.Parent;
            }

            if (selectedGroupNode == null)
                nodes = treeView1.Nodes;
            else
                nodes = selectedGroupNode.Nodes;

            INamedGroup g = CreateNewGroup();

            TreeNode newNode = CreateGroupNode(g);
            nodes.Add(newNode);
            if (selectedGroupNode != null)
            {
                INamedGroup parentGroup = selectedGroupNode.Tag as INamedGroup;
                //g.Parent = parentGroup;
                parentGroup.Groups.Add(g);
            }

            treeView1.SelectedNode = newNode;
            treeView1.Focus();
        }
        protected virtual INamedGroup CreateNewGroup()
        {
            throw new NotImplementedException("CreateNewGroup");
        }
        protected virtual INamedObject CreateNewItem()
        {
            throw new NotImplementedException("CreateNewItem");
        }
        private void AddOptionTreeNode()
        {
            TreeNode selectedGroupNode = treeView1.SelectedNode;
            if (selectedGroupNode != null)
            {
                if (!(selectedGroupNode.Tag is INamedGroup))
                    selectedGroupNode = selectedGroupNode.Parent;
            }
            if (selectedGroupNode != null)
            {
                INamedObject o = CreateNewItem();
                TreeNode newNode = CreateItemNode(o);
                (selectedGroupNode.Tag as INamedGroup).Items.Add(o);
                selectedGroupNode.Nodes.Add(newNode);
                treeView1.SelectedNode = newNode;
                treeView1.Focus();
            }
        }
        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            if (treeView1.SelectedNode.Tag is INamedGroup)
                treeView1.SelectedNode.Text = "[Group] " + (treeView1.SelectedNode.Tag as INamedGroup).Name;
            else
                treeView1.SelectedNode.Text = (treeView1.SelectedNode.Tag as INamedObject).Name;
        }

        internal void RefreshSelectedNode(bool forceGroup = false)
        {
            if (treeView1.SelectedNode != null)
            {
                if (forceGroup && !(treeView1.SelectedNode.Tag is INamedGroup))
                {
                    treeView1.SelectedNode = treeView1.SelectedNode.Parent;
                }
                if (treeView1.SelectedNode != null)
                {
                    INamedGroup g = treeView1.SelectedNode.Tag as INamedGroup;

                    if (g != null)
                    {
                        treeView1.SelectedNode.Text = "[Group] " + g.Name;
                        treeView1.SelectedNode.Nodes.Clear();
                        //foreach (Option o in g.Options)
                        AddOptionsNodes(treeView1.SelectedNode, g);

                        foreach (INamedGroup g2 in g.Groups)
                            AddGroupNode(treeView1.SelectedNode, g2);
                    }
                    else
                    {
                        treeView1.SelectedNode.Text = (treeView1.SelectedNode.Tag as INamedObject).Name;
                    }
                }
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            PrevInstance = Instance;
            Instance = this;
        }
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            Instance = PrevInstance;
            PrevInstance = null;
            if (Instance != null)
                Instance.RefreshSelectedNode();
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);

            if (!e.Cancel && DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                FillCollection(Collection);
            }
        }
        private void btnAddItem_Click(object sender, EventArgs e)
        {
            AddOptionTreeNode();
        }
    }
}
